﻿using System.Threading;
using FreshTexture.Settings;
using FreshTexture.View;
using Ionic.Zip;
using Ionic.Zlib;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows;

namespace FreshTexture.Model
{
    internal static class ZipIO
    {
        private static readonly BackgroundWorker BackgroundWorker = new BackgroundWorker();
        private static readonly ProgressWindow Progress = new ProgressWindow(MySettings.GetInt("SkipTickOnDepack"));
        private static Dictionary<string, MemoryStream> _unZipResult;
        private static string _fileNameUnpacking;
        private static bool _backgroundWorkerInitialized;

        public static void Unpack(Uri from)
        {
            InitProgressBar(@from);
            _unZipResult = new Dictionary<string, MemoryStream>();
            _unZipResult.Clear();
            InitBackgroundWorker(@from);
        }

        private static void InitProgressBar(Uri @from)
        {
            Progress.ProgressBar1.Maximum = new ZipFile(@from.LocalPath).Entries.Count;
            Progress.ProgressBar1.Value = 0;
            Progress.Owner = MySettings.GetMainWindow();
            Progress.Show();
        }

        private static void InitBackgroundWorker(Uri @from)
        {
            if (!_backgroundWorkerInitialized)
            {
                BackgroundWorker.DoWork += BackgroundWorkerDoWork;
                BackgroundWorker.RunWorkerCompleted += BackgroundWorkerRunWorkerCompleted;
                BackgroundWorker.ProgressChanged += BackgroundWorkerProgressChanged;
                BackgroundWorker.RunWorkerCompleted += BackgroundWorkerRunWorkerCompleted;
                BackgroundWorker.WorkerReportsProgress = true;
                BackgroundWorker.WorkerSupportsCancellation = true;
            }
            _backgroundWorkerInitialized = true;

            if (!BackgroundWorker.IsBusy)
            {
                BackgroundWorker.RunWorkerAsync(@from);
            }
        }

        private static void BackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Progress.ProgressBar1.Value = e.ProgressPercentage;
            Progress.UpdateProgressBarText(_fileNameUnpacking);
        }

        private static void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Progress.Visibility = Visibility.Hidden;
        }

        private static void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            var where = e.Argument as Uri;
            if (String.IsNullOrEmpty(where.LocalPath))
            {
                return;
            }

            _unZipResult.Clear();

            Debug.WriteLine(where);

            using (ZipFile zip = ZipFile.Read(where.LocalPath))
            {
                int count = 0;
                var memoryStream = new MemoryStream();
                foreach (ZipEntry zipEntry in zip)
                {
                    if (BackgroundWorker.CancellationPending)
                    {
                        return;
                    }
                    if (zipEntry.IsDirectory != true)
                    {
                        _unZipResult.Add(zipEntry.FileName, memoryStream);
                        _fileNameUnpacking = zipEntry.FileName;
                    }
                    BackgroundWorker.ReportProgress(count);
                    count++;
                    Thread.Sleep(5);
                }
            }
        }

        public static void Pack(Uri from, Uri where, string filename)
        {
            using (var zip = new ZipFile())
            {
                zip.AddDirectory(from.LocalPath);
                zip.Comment = "This zip was created in Fresh Texture - a tool to combine u own texture pack ";
                zip.CompressionLevel = CompressionLevel.Default;
                zip.Save(where.ToString());
            }
        }

        public static void AbortButton(object routedEventArgs)
        {
            if (!BackgroundWorker.IsBusy)
            {
                return;
            }
            BackgroundWorker.CancelAsync();
        }
    }
}